﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using StockManagement.Commands;
using System.Collections.ObjectModel;
using StockManagement.Helper;
using StockManagement.Model;

namespace StockManagement.ViewModels
{
    public class EditProductViewModel:BaseViewModel
    {
        ProductViewModel _productVM;
        string _materialName;
        EnumMaterialType _productType;
        ProductStatus _productStatus;
        bool _bProdMatModified;

        DelegateCommand _updateCommand;
        DelegateCommand _discardCommand;
        DelegateCommand _deleteCommand;
                
        public event ProductDeletedDelegate ProductDeleted;
        public event ProdUpdatedDelegate ProductUpdated;

        ObservableCollection<MaterialViewModel> _allMaterialCollection;
        ProductMaterialListViewModel _editProductMaterialCollection = new ProductMaterialListViewModel();
        ObservableCollection<ProductViewModel> _allProductCollection ;

        public EditProductViewModel(ObservableCollection<MaterialViewModel> allMaterialCollection, ObservableCollection<ProductViewModel> allProductCollection)
        {
            PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(EditProductViewModel_PropertyChanged);
            _allMaterialCollection = allMaterialCollection;
            _allProductCollection = allProductCollection;
            _allMaterialCollection.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(_allMaterialCollection_CollectionChanged);

            foreach (var item in _allMaterialCollection)
                AddProductMaterial(item);

            _updateCommand = new DelegateCommand(ExecuteUpdateProductCommand, CanExecuteUpdateMaterialCommand);
            _deleteCommand = new DelegateCommand(ExecuteDeleteCommand, CanExecuteDeleteCommand);
            _discardCommand = new DelegateCommand(ExecuteDiscardCommand);

            SelectedProduct = AllProductCollection.FirstOrDefault();
        }

        private void AddProductMaterial(MaterialViewModel item)
        {
            var itemProduct = new ProductMaterialViewModel(item.MaterialID, item.MaterialName, item.MaterialCode);
            _editProductMaterialCollection.Add(itemProduct);
        }

        void _allMaterialCollection_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            switch (e.Action)
            {
                case System.Collections.Specialized.NotifyCollectionChangedAction.Add:
                    if (e.NewItems.Count > 0)
                    {
                        var coll = e.NewItems.Cast<MaterialViewModel>();
                        foreach (var item in coll)
                        {
                            AddProductMaterial(item);
                        }
                    }
                    break;
                case System.Collections.Specialized.NotifyCollectionChangedAction.Remove:
                    if (e.OldItems.Count > 0)
                    {
                        var coll = e.OldItems.Cast<MaterialViewModel>();
                        foreach (var item in coll)
                        {
                            var prodmat = _editProductMaterialCollection.FirstOrDefault(p => p.MaterialID.Equals(item.MaterialID));
                            if (prodmat == null)
                                continue;

                            _editProductMaterialCollection.Remove(prodmat);
                        }
                    }
                    break;
                default:
                    break;
            }
        }

        void EditProductViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
                case "SelectedProduct":
                    InitializeProperties();
                    break;
                default:
                    break;
            }
            DeleteCommand.RaiseCanExecuteChanged();
            UpdateCommand.RaiseCanExecuteChanged();
        }

        public ProductViewModel SelectedProduct
        {
            get
            {
                return _productVM;
            }
            set
            {
                _productVM = value;
                OnPropertyChanged("SelectedProduct");
            }
        }

        private void InitializeProperties()
        {
            if (_productVM == null)
                return;

            ProductName = _productVM.ProductName;
            ProductType = _productVM.ProductType;
            ProductStatus = _productVM.ProductStatus;
            _editProductMaterialCollection = new ProductMaterialListViewModel();

            foreach (var item in _allMaterialCollection)
            {
                var mat = new ProductMaterialViewModel(item.MaterialID,item.MaterialName,item.MaterialCode);
                mat.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(mat_PropertyChanged);
                _editProductMaterialCollection.Add(mat);
            }

            foreach (var item in _productVM.MaterialsQuantity)
            {
                var prodmat = _editProductMaterialCollection.FirstOrDefault(p => p.MaterialID == item.MaterialID);
                if (prodmat == null)
                    continue;

                prodmat.IsSelected = true;
                prodmat.MaterialQuantity = item.MaterialQuantity;
            }
            OnPropertyChanged("AllProductMaterialCollection");
            _bProdMatModified = false;
        }

        void mat_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
                case "MaterialQuantity":
                case "IsSelected":
                    _bProdMatModified = true;
                    break;
                default:
                    break;
            }
        }

        public ProductMaterialListViewModel AllProductMaterialCollection
        {
            get
            {
                return _editProductMaterialCollection;
            }
        }

        public ObservableCollection<ProductViewModel> AllProductCollection
        {
            get
            {
                return _allProductCollection;
            }
        }

        public DelegateCommand UpdateCommand
        {
            get
            {
                return _updateCommand;
            }
        }

        public DelegateCommand DiscardCommand
        {
            get { return _discardCommand; }
        }

        public DelegateCommand DeleteCommand
        {
            get { return _deleteCommand; }
        }

        public string ProductName
        {
            get { return _materialName; }
            set
            {
                _materialName = value;
                OnPropertyChanged("ProductName");
            }
        }

        public EnumMaterialType ProductType
        {
            get { return _productType; }
            set
            {
                _productType = value;
                OnPropertyChanged("ProductType");
            }
        }

        public ProductStatus ProductStatus
        {
            get { return _productStatus; }
            set
            {
                _productStatus = value;
                OnPropertyChanged("ProductStatus");
            }
        }

        private ProductStatus GetProductStatus()
        {
            switch (ProductType)
            {
                case EnumMaterialType.Trading:
                    return ProductStatus.Outward_ToBeDeliverd;
                case EnumMaterialType.Manufacturing:
                default:
                    return ProductStatus.Defined;
            }
        }

        private bool CanExecuteUpdateMaterialCommand(object parameter)
        {
            if (_productVM == null)
                return false;

            if (ProductName.Trim() != _productVM.ProductName ||
                ProductType != _productVM.ProductType ||
                ProductStatus == Helper.ProductStatus.Defined ||
                ProductStatus == Helper.ProductStatus.Outward_ToBeDeliverd ||
                _bProdMatModified)
                return true;
            return false;
        }

        private void ExecuteUpdateProductCommand(object parameter)
        {
            ProductMaterialList list = new ProductMaterialList();
            foreach (var item in AllProductMaterialCollection)
            {
                if (!item.IsSelected)
                    continue;
                list.Add(item.Material);
            }
            
            if(!_productVM.UpdateProduct(UpdateType.Edit, ProductName, list))
                return;

            UpdateMaterialProperties();
        }

        private void UpdateMaterialProperties()
        {
            if (ProductUpdated != null)
                ProductUpdated();
        }

        private void ExecuteDiscardCommand(object parameter)
        {
            InitializeProperties();
            UpdateCommand.RaiseCanExecuteChanged();
        }

        private bool CanExecuteDeleteCommand(object parameter)
        {
            if (_productVM == null)
                return false;

            return (SelectedProduct.ProductStatus == Helper.ProductStatus.Defined);
        }

        private void ExecuteDeleteCommand(object item)
        {
            if (_productVM.DeleteProduct() && ProductDeleted != null)
                ProductDeleted(_productVM.ProductID);
            DeleteCommand.RaiseCanExecuteChanged();
        }
    }
}
